﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DataShower.Models;
using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Wpf;
using System.IO;
using System.Windows.Data;
using System.Windows.Media;

namespace DataShower.ViewModels
{
    public partial class DataViewModel : ObservableObject
    {
        /// <summary>
        /// 文件路径
        /// </summary>
        private string _filePath { get; }

        /// <summary>
        /// 数据
        /// </summary>
        public ChartValues<DataModel> DataList { get; } = new ChartValues<DataModel>();

        [ObservableProperty]
        AxesCollection yAxis;

        [ObservableProperty]
        SeriesCollection lineSeriesList;

        [ObservableProperty]
        double xMax = 2;

        [ObservableProperty]
        double xMin = 0;

        [ObservableProperty]
        double yMax = 200;

        [ObservableProperty]
        double yMin = 100;

        /// <summary>
        /// Y 值个数
        /// </summary>
        internal int YCount { get; set; } = 1;

        public string[] YNames { get; private set; }

        /// <summary>
        /// 图表数据转换
        /// </summary>
        public Func<double, string> DoubleFormater => x => $"{x:0.00}";

        public DataViewModel(string filePath)
        {
            _filePath = filePath;

            ReadYCount();

            InitChart();
            InitYAxes();
        }

        /// <summary>
        /// 计算当前文件有几条Y值
        /// </summary>
        private void ReadYCount()
        {
            if (!File.Exists(_filePath)) return;

            string? line = null;
            using (StreamReader reader = new StreamReader(_filePath))
            {
                if (!reader.EndOfStream)
                {
                    line = reader.ReadLine();
                }
            }

            if (string.IsNullOrWhiteSpace(line)) return;

            string[] contents = line.Split('\t', ' ');
            if (contents.Length > 1)
            {
                YCount = contents.Length - 1;
            }

            YNames = Enumerable.Range(1, YCount).Select(i => $"Y{i}").ToArray();
        }

        /// <summary>
        /// 初始化图标数据
        /// </summary>
        /// <param name="yCount"></param>
        private void InitChart()
        {
            LineSeriesList = new SeriesCollection();
            for (int i = 0; i < YCount; i++)
            {
                int index = i;
                var mapper = Mappers.Xy<DataModel>()
                        .X(mo => mo.X)
                        .Y(mo => mo.Y[index]);

                var line = new LineSeries()
                {
                    Fill = Brushes.Transparent,
                    PointGeometry = null,
                    Title = YNames[index],
                    DataLabels = false,
                    Foreground = Brushes.White,
                    Values = DataList,
                    ScalesYAt = index,
                    Configuration = mapper,
                };
                LineSeriesList.Add(line);
            }
        }

        public void InitYAxes()
        {
            YAxis = new AxesCollection();
            for (int i = 0; i < YCount; i++)
            {
                int index = i;

                Axis ax = new Axis()
                {
                    LabelFormatter = DoubleFormater,
                    FontSize = 10,
                    Separator = new Separator()
                    {
                        StrokeThickness = 1,
                        Stroke = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255))
                    },
                };

                Binding bin = new Binding();
                bin.Source = LineSeriesList[i];
                bin.Path = new System.Windows.PropertyPath("Stroke");
                BindingOperations.SetBinding(ax, Axis.ForegroundProperty, bin);

                YAxis.Add(ax);
            }
        }

        [RelayCommand]
        async Task LoadData()
        {
            DataList.Clear();

            string? line = null;
            using (StreamReader reader = new StreamReader(_filePath))
            {
                while ((line = reader.ReadLine()) != null)
                {
                    int[] y = ParseData(line, out double x);
                    XMax = Math.Max(XMax, x);
                    XMin = Math.Min(XMin, x);

                    YMax = Math.Max(YMax, y.Max());
                    YMin = Math.Min(YMin, y.Min());

                    DataModel data = new DataModel(DataList.Count + 1, x, y);
                    DataList.Add(data);
                    await Task.Delay(TimeSpan.FromSeconds(0.1));
                }
            }
        }

        /// <summary>
        /// 解析数据
        /// </summary>
        /// <param name="line"></param>
        /// <param name="x"></param>
        /// <returns></returns>
        private int[] ParseData(string line, out double x)
        {
            x = 0;
            int[] y = new int[YCount];

            string[] contents = line.Split('\t', ' ');
            List<double> nums = contents.Select(t =>
            {
                double.TryParse(t, out double n);
                return n;
            }).ToList();

            if (nums.Count > 0)
            {
                x = nums[0];
                nums.RemoveAt(0);

                for (int i = 0; i < Math.Min(YCount, nums.Count); i++)
                {
                    y[i] = Convert.ToInt32(nums[i]);
                }
            }

            return y;
        }
    }
}